import re
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django.contrib.auth import login
from django.db import DatabaseError
from django.http import JsonResponse, HttpResponseForbidden, HttpResponseServerError
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django_redis import get_redis_connection

from apps.carts.utils import merge_cart_cookie_to_redis
from apps.oauth.models import OAuthQQUser
from apps.oauth.utils import SecretOauth
from apps.users.models import User
from meiduo_mall.settings.dev import logger
# Create your views here.
class QQAuthURLView(View):
    def get(self, request):
        next = request.GET.get('next') #表示从哪个页面进到登录页面,将来登录成功后就跳转到哪个页面
        # 实例化QQ工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI, state=next)
        login_url = oauth.get_qq_url()
        return JsonResponse({'code':0, 'errmsg':'OK', 'login_url':login_url})
class QQAuthUserView(View): #用户扫码登录回调处理,登录QQ成功后,会传给我们一个Code
    def get(self, request):
        code = request.GET.get('code') #接收Code
        if not code:
            return HttpResponseForbidden('缺少code')
        # 实例化QQ工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET, redirect_uri=settings.QQ_REDIRECT_URI)
        try: #使用code向QQ服务器请求token, 使用token向QQ服务器请求openid
            access_token = oauth.get_access_token(code)
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            logger.error(e)
            return HttpResponseServerError('OAuth2.0认证失败')
        try: #判断openid是否绑定过用户
            oauth_user = OAuthQQUser.objects.get(openid=openid) #使用openid查询QQ用户是否绑定过美多商城
        except OAuthQQUser.DoesNotExist:
            secret_openid = SecretOauth().dumps(openid).decode() #加密完成之后返回的是bytes类型,需要decode()
            context = {'openid':secret_openid}
            return render(request, 'oauth_callback.html', context)
        else: #如果已绑定,则保持登录状态,跳转至next网页
            qq_user = oauth_user.user
            login(request, qq_user)
            next = request.GET.get('state')
            response = redirect(next)
            response.set_cookie('username', qq_user.username, max_age=3600*24*15)
            return response
    def post(self,request):
        mobile = request.POST.get('mobile')
        pwd = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        secret_openid = request.POST.get('openid')
        if not all([mobile, pwd, sms_code_client]):
            return HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseForbidden('请输入正确的手机号码')
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', pwd):
            return HttpResponseForbidden('请输入8-20位的密码')
        redis_conn = get_redis_connection('sms_code') #连接短信验证码redis数据库
        sms_code_server = redis_conn.get('sms_%s' %mobile) #判断短信验证码是否一致
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg':'短信验证码过期了'})
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg':'输入短信验证码有误'})
        openid = SecretOauth().loads(secret_openid) #解密openid,可以先将secret_openid进行encode()
        if not openid:
            return render(request, 'oauth_callback.html', {'openid_errmsg':'无效的openid'})
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            user = User.objects.create_user(username=mobile, password=pwd, mobile=mobile)
        else:
            if not user.check_password(pwd):
                return render(request, 'oauth_callback.html', {'account_errmsg':'用户名或密码错误'})
        try:
            OAuthQQUser.objects.create(openid=openid, user=user)
        except DatabaseError:
            return render(request, 'oauth_callback.html', {'qq_login_errmsg':'QQ登录失败'})
        login(request, user)
        next = request.GET.get('state')
        response = redirect(next)
        response.set_cookie('username', user.username, max_age=3600*24*15)
        # 合并购物车
        response = merge_cart_cookie_to_redis(request=request, user=user, response=response)
        return response

